Skip to content

Comments

fix : sprint3 스터디 퍼널 개선#370

Merged
seong-jin-jo merged 6 commits intodevelopfrom
feat/SRPINT3/enhance-journey-path
Feb 3, 2026
Merged

fix : sprint3 스터디 퍼널 개선#370
seong-jin-jo merged 6 commits intodevelopfrom
feat/SRPINT3/enhance-journey-path

Conversation

@seong-jin-jo
Copy link
Contributor

@seong-jin-jo seong-jin-jo commented Feb 3, 2026

url 기반으로 판단하는게 확장성있는 판단일까

🌱 연관된 이슈

☘️ 작업 내용

  • 그룹스터디/멘토스터디 기본값을 모집중으로
  • 그룹스터디/멘토스터디 상단에 참여중인 스터디 목록 (더보기시 마이페이지)

🍀 참고사항

스크린샷 (선택)

Summary by CodeRabbit

  • New Features

    • Added a "My Participating Studies" section to Group and Premium study list pages, showing up to three studies with links and a "view all" option.
  • Bug Fixes

    • Study list pages now default to showing recruiting studies when no filter is set.
    • Toggling the recruiting filter persists as true/false in the URL so turning it off is preserved.
    • Reset and filter state consistently treat recruiting as the default (true) while allowing explicit false.
  • Chores

    • Updated project ignore rules to include an additional config file.
    • Expanded type coverage for premium studies and reduced unnecessary data requests when no member is present.

url 기반으로 판단하는게 확장성있는 판단일까
@vercel
Copy link

vercel bot commented Feb 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
study-platform-client-dev Ready Ready Preview, Comment Feb 3, 2026 6:25pm

@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

Recruiting now defaults to true (absence of URL param => recruiting shown). The filter treats recruiting=true as the default (not an active filter) and persists explicit 'false' to disable it. A new client-side MyParticipatingStudiesSection was added and rendered on group and premium list pages. Minor type and tooling updates included.

Changes

Cohort / File(s) Summary
Filter Component
src/components/filtering/study-filter.tsx
Default recruiting set to true; hasAnyFilter logic inverted so recruiting === true is not counted as an applied filter; reset restores recruiting to true; clarifying comment added.
Group & Premium Study List Pages
src/components/pages/group-study-list-page.tsx, src/components/pages/premium-study-list-page.tsx
Import and render MyParticipatingStudiesSection (classification="GROUP_STUDY" / "PREMIUM_STUDY"). URL-reading now defaults recruiting to true when absent; parsed recruiting stored as explicit 'true' or 'false' on updates; data fetching and param-updating logic adjusted to preserve explicit false.
New UI Section (My Participating Studies)
src/components/section/my-participating-studies-section.tsx
Added new client-side component that requires classification, checks auth, fetches member studies and all studies, derives up to 3 participating (IN_PROGRESS/RECRUITING) studies, renders StudyCard grid and "전체보기", and emits analytics on clicks.
API Types
src/features/study/group/api/group-study-types.ts
Expanded union types to include PREMIUM_STUDY for MemberStudyListRequest.studyType and MemberStudyItem.type.
Member Study Query
src/features/study/group/model/use-member-study-list-query.ts
Added enabled option to skip query when memberId <= 0.
Formatting / Tooling
.prettierignore
Added blank line and new ignore entry .coderabbit.yaml.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as "Filter UI\n(src/components/filtering)"
  participant Page as "List Page\n(group / premium)"
  participant URL as "URL SearchParams"
  participant API as "Data Fetcher / API"

  UI->>Page: changeFilter(recruiting: true|false)
  Page->>URL: setSearchParam('recruiting' = 'true'|'false')
  Note right of URL: absent param => pages default recruiting = true
  URL-->>Page: updated params
  Page->>API: fetchStudies(params with recruiting parsed (default true))
  API-->>Page: studies
  Page-->>UI: render updated list
Loading
sequenceDiagram
  autonumber
  participant Section as "MyParticipatingStudiesSection"
  participant Auth as "Auth Hook"
  participant MemberAPI as "useMemberStudyListQuery"
  participant StudiesAPI as "useGetStudies"
  participant GA as "Analytics"

  Section->>Auth: ensureAuthenticated()
  Auth-->>Section: memberId (or null)
  Section->>MemberAPI: fetchMemberStudies(memberId, studyType)
  MemberAPI-->>Section: memberStudyItems
  Section->>StudiesAPI: fetchAllStudies(classification)
  StudiesAPI-->>Section: allStudies
  Section->>Section: derive participatingStudies (filter & cross-ref)
  Section-->>UI: render StudyCard grid (up to 3) + "전체보기" if more
  UI->>GA: handleStudyClick(studyId, hashedMemberId, title)
  GA-->>UI: eventRecorded
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hop through params, sniffing true,
Default blossoms open — filters few,
A little section shows who plays,
Cards and links in sunny arrays,
I twitch my nose — the code feels new.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title refers to improving the study funnel (스터디 퍼널 개선) which aligns with changes across multiple files that enhance the study list experience by adding a participating studies section, adjusting filter defaults, and updating URL parameter handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/SRPINT3/enhance-journey-path

Comment @coderabbitai help to get the list of available commands and usage tips.

@seong-jin-jo
Copy link
Contributor Author

@coderabbitai help

@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
    • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
    • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit configuration file (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/components/section/my-participating-studies-section.tsx`:
- Line 1: Run Prettier to fix formatting issues in this component file: execute
"prettier --write" (or your project's configured formatter) against
src/components/section/my-participating-studies-section.tsx (the
MyParticipatingStudiesSection component file) and commit the resulting changes
so the CI style check passes.
- Around line 24-26: The component calls hooks conditionally because of the
early return when memberId is falsy; move all hooks (useMemberStudyListQuery,
useGetStudies, useMemo, etc.) to the top of the component so they run
unconditionally, then handle the unauthenticated/render-empty case in the JSX
return instead of returning early, or alternatively keep hooks at top but add
the query option enabled: !!memberId (and pass memberId ?? 0 to the query input)
for useMemberStudyListQuery so queries are disabled until memberId exists.
🧹 Nitpick comments (1)
src/components/pages/premium-study-list-page.tsx (1)

81-128: Consider extracting shared URL filter logic into a custom hook.

The filterValues, updateSearchParams, and handleFilterChange logic is nearly identical between GroupStudyListPage and PremiumStudyListPage. A shared useStudyFilterParams(basePath: string) hook could reduce duplication. This is optional and can be deferred.

@@ -0,0 +1,196 @@
'use client';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Run Prettier to fix formatting issues.

The CI pipeline failed due to code style issues. Run prettier --write on this file to resolve.

🧰 Tools
🪛 GitHub Actions: CI

[warning] 1-1: Code style issues found in the file. Run 'prettier --write' to fix.


[error] 1-1: Prettier formatting check failed. Command 'prettier --check .' exited with code 1. Run 'prettier --write' to fix code style issues in this file.

🤖 Prompt for AI Agents
In `@src/components/section/my-participating-studies-section.tsx` at line 1, Run
Prettier to fix formatting issues in this component file: execute "prettier
--write" (or your project's configured formatter) against
src/components/section/my-participating-studies-section.tsx (the
MyParticipatingStudiesSection component file) and commit the resulting changes
so the CI style check passes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/components/section/my-participating-studies-section.tsx`:
- Around line 81-89: The component assumes allStudiesData is an object with a
content array but useGetStudies returns the array directly; update the
participatingStudies logic to treat allStudiesData as an array (or change
useGetStudies to return the full response). Specifically, in the
participatingStudies computation (symbols: participatingStudies, allStudiesData,
participatingStudyIds, basicInfo.groupStudyId), change checks from
allStudiesData?.content to just allStudiesData and filter over allStudiesData
(e.g., allStudiesData.filter(...)) so the filter uses the actual array returned
by useGetStudies; alternatively modify useGetStudies to return { content: data }
so current code continues to work.
🧹 Nitpick comments (1)
src/components/section/my-participating-studies-section.tsx (1)

54-60: Avoid fetching studies for guests.

Even though Line 95 returns null, useGetStudies on Line 55 still fetches for unauthenticated users. Consider adding an enabled option to useGetStudies (or gating the component higher) to skip this network call.

Also applies to: 94-96

Comment on lines +81 to +89
const participatingStudies = useMemo(() => {
if (!allStudiesData?.content || participatingStudyIds.size === 0) {
return [];
}

// 내가 참여중인 스터디 ID에 해당하는 스터디만 필터링
const filtered = allStudiesData.content.filter((study) =>
participatingStudyIds.has(study.basicInfo?.groupStudyId ?? 0),
);
Copy link

@coderabbitai coderabbitai bot Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Potential data-shape mismatch with useGetStudies.

useGetStudies currently returns data.content (array), but this component treats allStudiesData as { content: ... }. That makes allStudiesData?.content undefined, so participatingStudies becomes empty. Align the data shape or update the hook to return the full response.

✅ Suggested fix (treat data as array)
-  const { data: allStudiesData, isLoading } = useGetStudies({
+  const { data: allStudiesData = [], isLoading } = useGetStudies({
     classification,
     page: 1,
     pageSize: 100, // 충분히 많이 가져와서 필터링
     recruiting: undefined, // 모든 상태 포함 (진행 중, 모집 중 모두)
   });

   // 내가 참여중인 스터디만 필터링 (최대 3개)
   const participatingStudies = useMemo(() => {
-    if (!allStudiesData?.content || participatingStudyIds.size === 0) {
+    if (participatingStudyIds.size === 0) {
       return [];
     }

     // 내가 참여중인 스터디 ID에 해당하는 스터디만 필터링
-    const filtered = allStudiesData.content.filter((study) =>
+    const filtered = allStudiesData.filter((study) =>
       participatingStudyIds.has(study.basicInfo?.groupStudyId ?? 0),
     );
🤖 Prompt for AI Agents
In `@src/components/section/my-participating-studies-section.tsx` around lines 81
- 89, The component assumes allStudiesData is an object with a content array but
useGetStudies returns the array directly; update the participatingStudies logic
to treat allStudiesData as an array (or change useGetStudies to return the full
response). Specifically, in the participatingStudies computation (symbols:
participatingStudies, allStudiesData, participatingStudyIds,
basicInfo.groupStudyId), change checks from allStudiesData?.content to just
allStudiesData and filter over allStudiesData (e.g., allStudiesData.filter(...))
so the filter uses the actual array returned by useGetStudies; alternatively
modify useGetStudies to return { content: data } so current code continues to
work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우선 이 부분은 한 번 추후에 확인해볼게. 백엔드 적절한 API가 없어서 임시로 전체 스터디 다 부른 후 내 스터디 ID set 과 일치하는것을 필터링하고 있는데 추후에 새로운 API 를 만들게 되면 해결될거야. 이 기능이 나중에 빠질수도 있어서 my-participating-studies-section.tsx 는 임시 컴포넌트 정도로 생각하자. 추후에 스터디 개수가 늘어나면 리팩토링 해야돼.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seong-jin-jo, understood! I appreciate the context about this being a temporary implementation until the proper backend API is available.

Since this is technical debt that needs tracking, would you like me to create a GitHub issue to document the refactoring needed for my-participating-studies-section.tsx? The issue could outline:

  • The current implementation (fetching all studies + client-side filtering)
  • The proposed backend API improvement (endpoint accepting study IDs)
  • Performance concerns when study count scales

This way it won't be forgotten when the backend team is ready to implement the proper API.


✏️ Learnings added
Learnt from: seong-jin-jo
Repo: code-zero-to-one/study-platform-client PR: 370
File: src/components/section/my-participating-studies-section.tsx:81-89
Timestamp: 2026-02-03T18:49:50.822Z
Learning: The component `src/components/section/my-participating-studies-section.tsx` is a temporary implementation that fetches all studies and filters them client-side against the user's participating study ID set. This approach is used due to the lack of a suitable backend API. The component should be refactored or potentially removed in the future when a proper backend API becomes available.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

응 어떻게할건지 몰라도 해봐

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Create GitHub issue to track refactoring of my-participating-studies-section.tsx

gh issue create \
  --repo code-zero-to-one/study-platform-client \
  --title "Refactor my-participating-studies-section.tsx: Implement backend API for participating studies" \
  --body "## Context
This component is currently a temporary implementation that needs refactoring once a proper backend API becomes available.

**Related PR:** `#370`
**Comment discussion:** https://github.com/code-zero-to-one/study-platform-client/pull/370#discussion_r2760428556
**File:** \`src/components/section/my-participating-studies-section.tsx\`

## Current Implementation
The component currently:
- Fetches **all studies** via \`useGetStudies\` (paginated, but fetching 100 items)
- Fetches user's participating study list via \`useMemberStudyListQuery\`
- Creates a Set of participating study IDs client-side
- Filters the complete study list against this ID set on the client
- Limits to 3 studies for display

## Problem
- **Performance concern:** As the number of studies grows, fetching and filtering all studies client-side becomes inefficient
- **Data type mismatch:** The participating studies list and full studies list have different data structures, requiring this workaround
- **Network overhead:** Unnecessary data transfer for studies the user isn't participating in

## Proposed Solution
Implement one of these backend API improvements:

### Option 1: Batch fetch by IDs
\`\`\`
GET /api/v1/group-studies/by-ids?ids=1,2,3&classification=GROUP_STUDY
\`\`\`
Returns full study details for the specified IDs only.

### Option 2: Enhance existing endpoint
Modify \`getMemberStudyList\` to return all information needed for \`StudyCard\` rendering, eliminating the need for a second API call.

## Next Steps
- [ ] Backend team implements appropriate API endpoint
- [ ] Refactor component to use new endpoint
- [ ] Remove or optimize client-side filtering
- [ ] Consider whether this feature should remain permanent or be removed

## Notes
- This feature may be removed in the future depending on product decisions
- Component should be treated as temporary until refactoring is completed
- Requested by `@seong-jin-jo`" \
  --assignee seong-jin-jo

Length of output: 68


@seong-jin-jo, done! I've created issue #372 to track this refactoring work:

🔗 #372

The issue documents:

  • Current implementation (fetching all studies + client-side filtering)
  • Performance concerns as study count scales
  • Two proposed backend API solutions
  • Links back to this PR and discussion

The issue is assigned to you and includes checkboxes for tracking progress. Feel free to edit it if you'd like to adjust priorities or add more details!


🧠 Learnings used
Learnt from: seong-jin-jo
Repo: code-zero-to-one/study-platform-client PR: 370
File: src/components/section/my-participating-studies-section.tsx:81-89
Timestamp: 2026-02-03T18:49:50.822Z
Learning: The component `src/components/section/my-participating-studies-section.tsx` is a temporary implementation that fetches all studies and filters them client-side against the user's participating study ID set. This approach is used due to the lack of a suitable backend API. The component should be refactored or potentially removed in the future when a proper backend API becomes available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant